package com.element.oauth2.token;

import com.common.core.exception.ExceptionFactory;
import com.element.oauth2.constant.SecurityParams;
import io.netty.util.internal.StringUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsent;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 确认授权持久化
 * 资源拥有者（Resource Owner）对授权的确认信息OAuth2AuthorizationConsent的持久化
 */
@Configuration
public class RedisOAuth2AuthorizationConsentService implements OAuth2AuthorizationConsentService {

    @Resource
    private RedisTemplate<String, OAuth2AuthorizationConsent> redisTemplate;

    /**
     * 授权确认时间(秒)
     */
    private final static Long TIMEOUT = 60L * 10;

    @Override
    public void save(OAuth2AuthorizationConsent authorizationConsent) {
        if (null == authorizationConsent) {
            throw ExceptionFactory.sysException("授权确认为空");
        }
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setValueSerializer(RedisSerializer.java());
        redisTemplate.opsForValue().set(buildKey(authorizationConsent), authorizationConsent, TIMEOUT, TimeUnit.SECONDS);
    }

    @Override
    public void remove(OAuth2AuthorizationConsent authorizationConsent) {
        if (null == authorizationConsent) {
            throw ExceptionFactory.sysException("授权确认为空");
        }
        redisTemplate.delete(buildKey(authorizationConsent));
    }

    @Override
    public OAuth2AuthorizationConsent findById(String registeredClientId, String principalName) {
        if (StringUtil.isNullOrEmpty(registeredClientId) || StringUtil.isNullOrEmpty(principalName)) {
            throw ExceptionFactory.sysException("客户端ID或用户名为空");
        }
        return redisTemplate.opsForValue().get(buildKey(registeredClientId, principalName));
    }

    private String buildKey(OAuth2AuthorizationConsent authorizationConsent) {
        return buildKey(authorizationConsent.getRegisteredClientId(), authorizationConsent.getPrincipalName());
    }

    /**
     * @param registeredClientId 客户端ID
     * @param principalName      用户名称
     * @return key
     */
    private String buildKey(String registeredClientId, String principalName) {
        return SecurityParams.SPRING_SECURITY_CONSENT_KEY + registeredClientId + ":" + principalName;
    }
}